home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / misc / SmartReadArgs.lha / smartreadargs / SmartReadArgs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-07  |  23.0 KB  |  734 lines

  1. /*
  2.  * SmartReadArgs.c -- CLI/Workbench transparent ReadArgs()
  3.  *
  4.  * $VER: SmartReadArgs.c 1.6 (7.9.98)
  5.  *
  6.  * Copyright 1998 by Thomas Aglassinger <agi@sbox.tu-graz.ac.at>
  7.  *
  8.  * Based on ExtReadArgs Copyright 1994,1995 by Stefan Ruppert
  9.  */
  10.  
  11. /****** SmartReadArgs/--history-- *******************************************
  12.  * HISTORY
  13.  *   Version 1.6, 7-Sep-1998
  14.  *
  15.  *   - Changed name to SmartReadArgs to avoid confusion with other work based
  16.  *     on the same material
  17.  *   - Changed function parameters for SmartReadArgs() so that no more SAS/c
  18.  *     specific values of argc/argv are required (Of course it still works
  19.  *     with SAS/c, but you have to provide the WBStartup from "outside").
  20.  *   - Changed all #include <clib/...> to #include <proto/..>, except for
  21.  *     <clib/alib_stdio_protos.h> in "test.c". Where the hell is this one?
  22.  *   - Added feature to ignore tooltypes that are not in the template
  23.  *   - Added some missing includes in SmartReadArgs.c so the source codes
  24.  *     compile without warnings
  25.  *   - Changed #include <debug.h> to #include "debug.h" and provided a proper
  26.  *     debug.h
  27.  *   - The WINDOW tooltype is handled properly even if it is not entirely
  28.  *     written in upper case.
  29.  *   - Requires "utility.library" to be open as Stricmp() is used several
  30.  *     times
  31.  *   - Changed from Printf() to printf() using stdio of amiga.lib to make the
  32.  *     code compile easier on non-SAS environments
  33.  *   - Changed autodoc tool to Robodoc
  34.  *   - Fixed enforcer hit if no tooltypes were provided at all
  35.  *   - Remove some "char filename[34]" stuff and replaced the array dimension
  36.  *     by MAXIMUM_FILENAME_LENGTH for future compatibility
  37.  *   - Cleaned-up autodocs
  38.  * ANCIENT HISTORY
  39.  *   ExtReadArgs() by Stefan Ruppert
  40.  *
  41.  *   See aminet:dev/misc/extrdargs_v1.5.lha for the original version.
  42.  *
  43.  *   $HISTORY
  44.  *   08.01.95 : 001.005 :  changed to ExtReadArgs()
  45.  *   24.09.94 : 001.004 :  now checks after ReadArgs the SIGBREAKF_CTRL_C
  46.  *                         flag, thus if anyone canceled during ReadArgs()
  47.  *                         help ExtReadArgs() fails
  48.  *   08.09.94 : 001.003 :  between two switches (no equal sign) there was
  49.  *                         no space, this is fixed
  50.  *   08.09.94 : 001.002 :  wb files now enclosed in quotes
  51.  *   04.09.94 : 001.001 :  bumped to version 1
  52.  *   19.05.94 : 000.001 :  initial
  53.  ***************************************************************************/
  54.  
  55. /* ------------------------------ include's ------------------------------- */
  56.  
  57. #include "debug.h"
  58. #include "SmartReadArgs.h"
  59.  
  60. #include <exec/memory.h>
  61. #include <workbench/startup.h>
  62. #include <workbench/workbench.h>
  63. #include <dos/exall.h>
  64. #include <utility/tagitem.h>
  65.  
  66. #include <string.h>
  67.  
  68. #include <proto/dos.h>
  69. #include <proto/icon.h>
  70. #include <proto/exec.h>
  71. #include <proto/utility.h>
  72.  
  73. /* ---------------------------- local defines ----------------------------- */
  74.  
  75. #define TEMPSIZE                     512
  76. #ifndef MAX
  77. #define MAX(a,b)  (((a) > (b)) ? (a) : (b))
  78. #endif
  79.  
  80. #ifndef EOS
  81. #define EOS    '\0'
  82. #endif
  83.  
  84. #define MODE_MULTI      1
  85.  
  86. #define MAXIMUM_FILENAME_LENGTH 108
  87.  
  88. /* --------------------------- library bases ------------------------------ */
  89. extern struct Library *IconBase;
  90. extern struct Library *UtilityBase;
  91.  
  92. #ifdef __GNUC__
  93. extern struct WBStartup *_WBenchMsg;
  94. #endif
  95.  
  96. /* -------------------------- static prototypes --------------------------- */
  97.  
  98. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wbarg);
  99. static void fstrcpy(struct SmartArgs *args, STRPTR string);
  100. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes);
  101. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size);
  102. static BOOL is_in_template(STRPTR name, STRPTR template);
  103.  
  104. /****** SmartReadArgs/--background-- ****************************************
  105.  * COPYRIGHT
  106.  *   SmartReadArgs is Copyright 1998 Thomas Aglassinger
  107.  *
  108.  *   ExtReadArgs, its prequel, is Copyright 1994,1995 Stefan Ruppert
  109.  *
  110.  *   Permission is granted to freely distribute the material (also only
  111.  *   parts of it) as long this ReadMe is included and all the copyright
  112.  *   notes are left unaltered except for a description of your changes.
  113.  * MOTIVATION
  114.  *   The way of parsing ToolTypes provided by "icon.library" is rather
  115.  *   clumsy. This is particular annoying as many programmers and users got
  116.  *   used to ReadArgs(), which does the argument handling for many CLI
  117.  *   commands and ARexx ports.
  118.  *
  119.  *   Unfortunately, ReadArgs lacks a interface to Workbench tooltypes, thus
  120.  *   its usage preventes your programs from being started from Workbench.
  121.  *
  122.  *   SmartReadArgs() copies all Workbench arguments in a single string and
  123.  *   passes this string to the ReadArgs() function. If started from CLI, it
  124.  *   calls ReadArgs() without this step.
  125.  * AUTHOR
  126.  *   Stefan Ruppert wrote most parts of the source code, designed the general
  127.  *   interface and implemented loads of nice features. Basically he did the
  128.  *   "hard work".
  129.  *
  130.  *   He got the main idea for the implementation from Stefan Winterstein,
  131.  *   the author of ARoach.
  132.  *
  133.  *   Thomas Aglassinger <agi@sbox.tu-graz.ac.at> did some minor changes,
  134.  *   established a more consistent naming schema, reworked the documentation
  135.  *   and also added support for gcc/libnix.
  136.  *
  137.  *   Contact him in case of problems or if you made some enhancements.
  138.  *
  139.  *   Updates are available from aminet:dev/misc/SmartReadArgs.lha.
  140.  * DISCLAIMER
  141.  *   There is no warranty for this software package. Although the author
  142.  *   has tried to prevent errors, he can't guarantee that the software
  143.  *   package described in this document is 100% reliable. You are
  144.  *   therefore using this material at your own risk. The author cannot be
  145.  *   made responsible for any damage which is caused by using this
  146.  *   software package.
  147.  ****************************************************************************/
  148.  
  149. /* The define below is used to rename the example main() used in the autodoc
  150.  * to dummy_main(). Using two main()s would cause problems for the linker. */
  151. #define main dummy_main
  152.  
  153. /****** SmartReadArgs/SmartReadArgs ******************************************
  154.  * NAME
  155.  *   SmartReadArgs -- Workbench/CLI transparent ReadArgs().
  156.  * SYNOPSIS
  157.  *   error = SmartReadArgs(wb_startup, smart_args);
  158.  * 
  159.  *   LONG SmartReadArgs(struct WBStartup *, struct SmartArgs *);
  160.  * FUNCTION
  161.  *   This function is a CLI/Workbench transparent interface to ReadArgs().
  162.  *
  163.  *   In case of a Workbench start, it analyzes the WBStartup message and
  164.  *   possible tooltypes. These are converted to a text string that can be
  165.  *   passed to ReadArgs() like before.
  166.  *
  167.  *   Tooltypes that are not part of the template are ignored. This includes
  168.  *   tooltypes being disabled with "(...)", NewIcons image data on systems
  169.  *   without NewIcons installed and all this «« Icon by some idiot »» crap.
  170.  * 
  171.  *   If the application was stared from CLI, it simply calls ReadArgs()
  172.  *   without the conversion step.
  173.  *
  174.  *   If all went well you get a return value of zero. This means the passed
  175.  *   arguments fit the template and are ready to use. Otherwise you get a
  176.  *   IoErr()-like return code.
  177.  * INPUTS
  178.  *    wb_startup - Workbench startup message. Refer to your compiler manual
  179.  *        to learn how to obtain it. If this is NULL, the program was
  180.  *        started from CLI.
  181.  *    smart_args - structure which holds all information used by
  182.  *        SmartReadArgs(). You have to setup the following fields before the
  183.  *        call:
  184.  *
  185.  *        sa_Template - The template passed to ReadArgs()
  186.  *        sa_Parameter - ReadArgs() LONG WORD array to hold the arguments
  187.  *        sa_FileParameter - number of Argument in the template to use
  188.  *            for the files passed via WBStartup->sm_ArgList or -1, that
  189.  *            means you don't want any files
  190.  *        sa_Window - Window description string to open when the program
  191.  *            is started from the workbench. NULL means no window. If the
  192.  *            icon has a WINDOW tooltype, this value is ignored.
  193.  *        sa_RDArgs - RDArgs structure to use for ReadArgs() call. This
  194.  *            can be used to provide extended help.
  195.  *        sa_Buffer - Pointer to a buffer to use for the Workbench startup
  196.  *            or NULL, that means SmartReadArgs() allocates a buffer for you
  197.  *        sa_BufferSize - Size of the optional buffer. If it is smaller than
  198.  *            SA_MINIMUM_BUFFER_SIZE it will be adjusted.
  199.  *
  200.  *        All other fields should be set to NULL.
  201.  * RESULTS
  202.  *   Zero for success. You can check the sa_Flags field for the
  203.  *   SAF_WORKBENCH flag to learn how the program was started.
  204.  *
  205.  *   Otherwise an IoErr()-like error code is returned. This can be passed
  206.  *   directly to PrintFault() or similar.
  207.  * NOTES
  208.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! See example
  209.  *   below.
  210.  *
  211.  *   This function requires "dos.library", "icon.library" and
  212.  *   "utility.library" to be opened by the application. Normally this
  213.  *   already has been done by the compiler startup code.
  214.  *
  215.  *   There is a not widely known feature of ReadArgs(): with templates like
  216.  *   "FROM/M/A,TO/A", you can select the files from workbench performing the
  217.  *   following steps:
  218.  *
  219.  *   - Select the program
  220.  *   - Select the FROM files
  221.  *   - Select and double click the TO file
  222.  *
  223.  *   This is available because ReadArgs() grabs the last string from a
  224.  *   multi-argument FROM and uses it as the TO parameter, if none is passed
  225.  *   explicitely.
  226.  * BUGS
  227.  *   There are some known problems when used with GCC, mostly related to the
  228.  *   fact that I never bothered creating a useable developer environment
  229.  *   around it (and I'm not sure if this is even possible >:) ...):
  230.  *
  231.  *   - Debugging output shows up in the console instead of SER:. Does
  232.  *     debug.lib exist for gcc? (Wasn't there this strange hunk2gcc
  233.  *     converter?)
  234.  *   - "Read from 0" Enforcer hit in SmartReadArgs(). Couldn't figure out
  235.  *     the exact location yet because of the asynchronous debugging output
  236.  *     mentioned above.
  237.  *
  238.  *   For someone with a reasonable experience with GCC, it should be easy to
  239.  *   fix this.
  240.  *
  241.  *   The SAS/c implementation does not have these problems.
  242.  * SEE ALSO
  243.  *   SmartFreeArgs(), dos.library/ReadArgs(), icon.library/GetDiskObjectNew()
  244.  * EXAMPLE
  245.  *   The main archiev comes with a "test.c" and a couple of icons to start
  246.  *   the corresponding executable "test". Take a look at the source code and
  247.  *   play with it.
  248.  *
  249.  *   See below for a smaller code segment that expects the "dos.library",
  250.  *   "icon.library" and "utility.library" to be open already.
  251.  * SOURCE
  252.  */
  253. int main(int argc, STRPTR argv[])
  254. {
  255.    struct SmartArgs smart_args =
  256.    {NULL};
  257.    LONG argument[2];
  258.    LONG error;
  259.  
  260.    /* Obtain WBStartup; depends on your compiler environment */
  261.    struct WBStartup *wb_startup = NULL;
  262. #ifdef __GNUC__
  263.    wb_startup = _WBenchMsg;
  264. #else
  265.    if (argc == 0)
  266.    {
  267.       wb_startup = (struct WBStartup *) argv;
  268.    }
  269. #endif
  270.  
  271.    smart_args.sa_Template = "FILES/M/A,VERBOSE";
  272.    smart_args.sa_Parameter = argument;
  273.    smart_args.sa_FileParameter = 0;
  274.    smart_args.sa_Window = "CON:////My WB-Window/AUTO/CLOSE/WAIT";
  275.  
  276.    error = SmartReadArgs(wb_startup, &smart_args);
  277.    if (error == 0)
  278.    {
  279.       /* do something */
  280.    }
  281.    else
  282.    {
  283.       PrintFault(error, "MyProgram");
  284.    }
  285.  
  286.    SmartFreeArgs(&smart_args);
  287.  
  288.    return ((error == 0) ? RETURN_OK : RETURN_FAIL);
  289. }
  290. /****************************************************************************/
  291. LONG SmartReadArgs(struct WBStartup * wb_startup, struct SmartArgs * args)
  292. {
  293.    LONG error;
  294.  
  295.    args->sa_Flags = 0;
  296.  
  297.    D(bug("UtilityBase = 0x%lx\n", (ULONG) UtilityBase));
  298.    D(bug("IconBase    = 0x%lx\n", (ULONG) IconBase));
  299.    D(bug("WBStartup   = 0x%lx\n", (ULONG) wb_startup));
  300.  
  301.    if (wb_startup != NULL)
  302.    {
  303.       struct WBArg *wbarg = wb_startup->sm_ArgList;
  304.       LONG arg_counter = 0;
  305.  
  306.       D(bug("  numArgs   = %ld\n", wb_startup->sm_NumArgs));
  307.       while (arg_counter < wb_startup->sm_NumArgs)
  308.       {
  309.          D(bug("  name[%ld] = \"%s\"\n", arg_counter, wbarg->wa_Name));
  310.          wbarg += 1;
  311.          arg_counter += 1;
  312.       }               
  313.    }
  314.  
  315.    if (wb_startup != NULL)
  316.    {
  317.       if (!(args->sa_RDArgs = AllocDosObject(DOS_RDARGS, NULL)))
  318.       {
  319.          return (ERROR_NO_FREE_STORE);
  320.       }
  321.       else
  322.       {
  323.          args->sa_Flags |= SAF_ALLOCRDARGS;
  324.  
  325.          if (!args->sa_Buffer)
  326.          {
  327.             args->sa_BufferSize = MAX(SA_MINIMUM_BUFFER_SIZE, args->sa_BufferSize);
  328.             args->sa_Buffer = AllocMem(args->sa_BufferSize, MEMF_ANY);
  329.             args->sa_Flags |= SAF_ALLOCBUFFER;
  330.          }
  331.  
  332.          if (!args->sa_Buffer)
  333.             return (ERROR_NO_FREE_STORE);
  334.          else
  335.          {
  336.             struct DiskObject *dobj;
  337.  
  338.             args->sa_ActualPtr = args->sa_Buffer;
  339.             args->sa_EndPtr = args->sa_Buffer + args->sa_BufferSize - 1;
  340.  
  341.             if (!(dobj = smart_get_icon(args, wb_startup)))
  342.             {
  343.                return (ERROR_OBJECT_NOT_FOUND);
  344.             }
  345.             else
  346.             {
  347.                struct WBArg *wbarg = args->sa_WBArg;
  348.                ULONG num = args->sa_NumArgs;
  349.  
  350.                STRPTR *tooltypes = (STRPTR *) dobj->do_ToolTypes;
  351.                STRPTR name;
  352.                STRPTR temp;
  353.                STRPTR ptr;
  354.  
  355.                if (num > 1 && args->sa_FileParameter >= 0 && (temp = AllocMem(TEMPSIZE, MEMF_ANY)))
  356.                {
  357.                   ULONG modes = 0;
  358.  
  359.                   get_arg_name(args, temp, TEMPSIZE, &modes);
  360.                   fstrcpy(args, temp);
  361.                   fstrcpy(args, " ");
  362.  
  363.                   /* no "/M" specifier in the ReadArgs() template, thus use only the first file */
  364.                   if (modes != MODE_MULTI)
  365.                      num = 2;
  366.  
  367.                   while (num > 1)
  368.                   {
  369.                      get_wbarg_name(wbarg, temp, TEMPSIZE);
  370.                      fstrcpy(args, "\"");
  371.                      fstrcpy(args, temp);
  372.                      fstrcpy(args, "\" ");
  373.                      num--;
  374.                      wbarg++;
  375.                   }
  376.  
  377.                   FreeMem(temp, TEMPSIZE);
  378.                }
  379.  
  380.                D(bug("tooltypes=%lx\n", (ULONG) tooltypes));
  381.                if (tooltypes)
  382.                {
  383.                   while (*tooltypes)
  384.                   {
  385.                      ptr = *tooltypes;
  386.                      name = ptr;
  387.  
  388.                      /* check if this tooltype enabled and part of the
  389.                       * template */
  390.                      if ((*ptr != '(')
  391.                          && is_in_template(name, args->sa_Template))
  392.                      {
  393.                         while (*ptr != '=' && *ptr != EOS)
  394.                            ptr++;
  395.  
  396.                         if (*ptr == '=')
  397.                         {
  398.                            *ptr = EOS;
  399.  
  400.                            if (!Stricmp(name, "WINDOW"))
  401.                            {
  402.                               STRPTR win;
  403.                               if ((win = AllocVec(strlen(ptr + 1) + 1, MEMF_ANY)))
  404.                               {
  405.                                  strcpy(win, ptr + 1);
  406.                                  args->sa_Window = win;
  407.                                  args->sa_Flags |= SAF_ALLOCWINDOW;
  408.                               }
  409.  
  410.                            }
  411.                            else
  412.                            {
  413.                               fstrcpy(args, name);
  414.  
  415.                               /* enclose the argument in "" */
  416.                               if (*(ptr + 1) == '"')
  417.                               {
  418.                                  fstrcpy(args, "=");
  419.                                  fstrcpy(args, ptr + 1);
  420.                               }
  421.                               else
  422.                               {
  423.                                  fstrcpy(args, "=\"");
  424.                                  fstrcpy(args, ptr + 1);
  425.                                  fstrcpy(args, "\"");
  426.                               }
  427.  
  428.                               *ptr = '=';
  429.                            }
  430.                         }
  431.                         else
  432.                            fstrcpy(args, name);
  433.  
  434.                         fstrcpy(args, " ");
  435.                      }
  436.                      tooltypes++;
  437.                   }             /* while (*tooltypes) */
  438.                }                /* if (tooltypes) */
  439.                fstrcpy(args, "\n");
  440.  
  441.                D(bug("final wb command line : \"%s\"\n", args->sa_Buffer));
  442.             }
  443.          }
  444.       }
  445.  
  446.       args->sa_RDArgs->RDA_Source.CS_Buffer = args->sa_Buffer;
  447.       args->sa_RDArgs->RDA_Source.CS_Length = strlen(args->sa_Buffer);
  448.  
  449.       args->sa_Flags |= SAF_WORKBENCH;
  450.    }
  451.  
  452.    args->sa_FreeArgs = ReadArgs(args->sa_Template, args->sa_Parameter, args->sa_RDArgs);
  453.  
  454.    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  455.    {
  456.       SetIoErr(ERROR_BREAK);
  457.    }
  458.  
  459.    if ((error = IoErr()) == 0 && (wb_startup != NULL))
  460.    {
  461.       if (args->sa_Window)
  462.       {
  463.          args->sa_WindowFH = Open(args->sa_Window, MODE_NEWFILE);
  464.          if (args->sa_WindowFH)
  465.          {
  466.             args->sa_OldOutput = SelectOutput(args->sa_WindowFH);
  467.             args->sa_OldInput = SelectInput(args->sa_WindowFH);
  468.          }
  469.       }
  470.    }
  471.  
  472.    return (error);
  473. }
  474.  
  475. /****** SmartReadArgs/SmartFreeArgs ******************************************
  476.  * NAME
  477.  *   SmartFreeArgs -- Free all resources allocated by SmartReadArgs().
  478.  * SYNOPSIS
  479.  *   SmartFreeArgs(smart_args);
  480.  *
  481.  *   void SmartFreeArgs(struct SmartArgs *);
  482.  * FUNCTION
  483.  *   Free all resources allocated by a previous call to SmartReadArgs().
  484.  * INPUTS
  485.  *   smart_args - Same pointer as passed to SmartReadArgs() before
  486.  * NOTES
  487.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! Take a look
  488.  *   at the example for SmartReadArgs().
  489.  * SEE ALSO
  490.  *   SmartReadArgs()
  491.  ****************************************************************************/
  492. void SmartFreeArgs(struct SmartArgs *args)
  493. {
  494.    /* FreeArgs() can handle a NULL pointer */
  495.    FreeArgs(args->sa_FreeArgs);
  496.  
  497.    if (args->sa_Flags & SAF_ALLOCRDARGS)
  498.       if (args->sa_RDArgs)
  499.          FreeDosObject(DOS_RDARGS, args->sa_RDArgs);
  500.  
  501.    if (args->sa_Flags & SAF_ALLOCBUFFER)
  502.       FreeMem(args->sa_Buffer, args->sa_BufferSize);
  503.  
  504.    if (args->sa_WindowFH)
  505.    {
  506.       SelectOutput(args->sa_OldOutput);
  507.       SelectInput(args->sa_OldInput);
  508.       Close(args->sa_WindowFH);
  509.    }
  510.  
  511.    if (args->sa_Flags & SAF_ALLOCWINDOW && args->sa_Window)
  512.       FreeVec(args->sa_Window);
  513.  
  514. }
  515.  
  516. /* This code was grapped from IconImage/wbarg.c/IconFromWBArg()
  517.  * Commodore-Amiga Example code
  518.  */
  519. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wb_startup)
  520. {
  521.    struct DiskObject *dob = NULL;
  522.    struct WBArg *wbarg = wb_startup->sm_ArgList;
  523.    ULONG num = wb_startup->sm_NumArgs;
  524.  
  525.    UBYTE work_name[MAXIMUM_FILENAME_LENGTH];
  526.    BPTR old_lock, new_lock;
  527.  
  528.    /* Copy the WBArg contents */
  529.    strncpy(work_name, wbarg->wa_Name, MAXIMUM_FILENAME_LENGTH);
  530.  
  531.    new_lock = DupLock(wbarg->wa_Lock);
  532.    if (new_lock != NULL)
  533.    {
  534.       D(bug("work_name : \"%s\"\n", work_name));
  535.  
  536.       /* go to the directory where the icon resides */
  537.       old_lock = CurrentDir(new_lock);
  538.  
  539.       dob = GetDiskObjectNew(work_name);
  540.  
  541.       /* test, if the first icon is a project icon and if so, get its icon */
  542.       if (wb_startup->sm_NumArgs > 1)
  543.       {
  544.          BPTR new_lock2;
  545.  
  546.          if ((new_lock2 = DupLock(wbarg[1].wa_Lock)))
  547.          {
  548.             struct DiskObject *prj;
  549.  
  550.             CurrentDir(new_lock2);
  551.  
  552.             UnLock(new_lock);
  553.             new_lock = new_lock2;
  554.  
  555.             strncpy(work_name, wbarg[1].wa_Name, MAXIMUM_FILENAME_LENGTH);
  556.             D(bug("work_name2 : \"%s\"\n", work_name));
  557.  
  558.             if ((prj = GetDiskObjectNew(work_name)))
  559.             {
  560.                if (prj->do_Type == WBPROJECT)
  561.                {
  562.                   BPTR test;
  563.  
  564.                   /* if this is only an icon skip it */
  565.                   if (!(test = Lock(work_name, SHARED_LOCK)))
  566.                   {
  567.                      wbarg++;
  568.                      num--;
  569.                   }
  570.                   else
  571.                      UnLock(test);
  572.  
  573.                   if (dob)
  574.                      FreeDiskObject(dob);
  575.  
  576.                   dob = prj;
  577.                }
  578.             }
  579.          }
  580.       }
  581.  
  582.       if (dob)
  583.       {
  584.          D(bug("dobj window : %s\n", dob->do_ToolWindow));
  585.       }
  586.  
  587.       /* go back to where we used to be */
  588.       CurrentDir(old_lock);
  589.  
  590.       /* release the duplicated lock */
  591.       UnLock(new_lock);
  592.  
  593.       args->sa_WBArg = wbarg + 1;
  594.       args->sa_NumArgs = num;
  595.    }
  596.  
  597.    D(bug("return (dob)\n"));
  598.  
  599.    return (dob);
  600. }
  601.  
  602. static void fstrcpy(struct SmartArgs *args, STRPTR string)
  603. {
  604.    STRPTR ptr = args->sa_ActualPtr;
  605.    STRPTR end = args->sa_EndPtr;
  606.  
  607.    while (ptr < end && *string)
  608.       *ptr++ = *string++;
  609.  
  610.    *ptr = EOS;                  /* Mark end of string */
  611.  
  612.    args->sa_ActualPtr = ptr;
  613. }
  614.  
  615. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes)
  616. {
  617.    ULONG num = args->sa_FileParameter;
  618.    STRPTR ptr = args->sa_Template;
  619.  
  620.    *modes = 0;
  621.  
  622.    while (num > 0)
  623.    {
  624.       while (*ptr != ',' && *ptr != EOS)
  625.          ptr++;
  626.  
  627.       if (*ptr == ',')
  628.          ptr++;
  629.       num--;
  630.    }
  631.  
  632.    if (*ptr != EOS)
  633.    {
  634.       while (*ptr != ',' && *ptr != '/' && *ptr != EOS && size > 0)
  635.       {
  636.          *buffer++ = *ptr++;
  637.          size--;
  638.       }
  639.  
  640.       while (*ptr == '/')
  641.       {
  642.          ptr++;
  643.  
  644.          if (*ptr == 'M' || *ptr == 'm')
  645.             *modes = MODE_MULTI;
  646.  
  647.          ptr++;
  648.       }
  649.    }
  650.  
  651.    *buffer = EOS;
  652. }
  653.  
  654. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size)
  655. {
  656.    BPTR new;
  657.  
  658.    if ((new = DupLock(wbarg->wa_Lock)))
  659.    {
  660.       if (!NameFromLock(new, buffer, size))
  661.          *buffer = EOS;
  662.       else if (!AddPart(buffer, wbarg->wa_Name, size))
  663.          *buffer = EOS;
  664.  
  665.       UnLock(new);
  666.    }
  667.    else
  668.       *buffer = EOS;
  669. }
  670.  
  671. /* Enable extended debugging for is_in_template() */
  672. #if 0
  673. #define D2(x) x
  674. #else
  675. #define D2(x) /* nufin */
  676. #endif
  677. static BOOL is_in_template(STRPTR name, STRPTR template)
  678. {
  679.    BOOL found = FALSE;
  680.    STRPTR current_word = template;
  681.    BOOL skip_switch = FALSE;
  682.    size_t name_length;
  683.  
  684.    /* Evaluate length of name part of whole tooltype */
  685.    name_length = 0;
  686.    while ((name[name_length] != EOS)
  687.           && (name[name_length] != '='))
  688.    {
  689.       name_length += 1;
  690.    }
  691.  
  692.    D(bug("find `%s' in template `%s'\n", name, template));
  693.    while ((current_word[0] != '\0') && (!found))
  694.    {
  695.       STRPTR next_word = strpbrk(current_word, "/=,");
  696.       size_t current_word_length;
  697.  
  698.       if (next_word == NULL)
  699.       {
  700.          next_word = current_word + strlen(current_word);
  701.       }
  702.       current_word_length = next_word - current_word;
  703.  
  704.       if (skip_switch)
  705.       {
  706.          D2(bug("  skip  (`%s', %lu)\n", current_word, current_word_length));
  707.          skip_switch = FALSE;
  708.       }
  709.       else
  710.       {
  711.          D2(bug("  check (`%s', %lu)\n", current_word, current_word_length));
  712.          if ((name_length == current_word_length)
  713.              && !Strnicmp(name, current_word, name_length))
  714.          {
  715.             D(bug("  found!\n"));
  716.             found = TRUE;
  717.          }
  718.       }
  719.  
  720.       current_word = next_word;
  721.       if (current_word[0] != '\0')
  722.       {
  723.          if (current_word[0] == '/')
  724.          {
  725.             skip_switch = TRUE;
  726.          }
  727.          current_word += 1;
  728.       }
  729.    }
  730.  
  731.    return found;
  732. }
  733.  
  734.